/**
 * 优化版 vs 标准版 Quadtree 性能对比
 * 
 * @description
 * 测试各项优化的实际效果
 */

import { Quadtree } from './Quadtree';
import { QuadtreeOptimized } from './QuadtreeOptimized';
import { Rectangle } from './Rectangle';
import { Log } from '../logger/LoggerGlobal';

/**
 * 性能对比测试
 */
export class OptimizationComparison {
    
    /**
     * 测试 1: 大量插入性能
     */
    static testMassiveInsert(): void {
        Log.styled('='.repeat(60), 'separator');
        Log.styled('测试 1: 大量插入性能', 'title');
        Log.styled('='.repeat(60), 'separator');
        
        const counts = [100, 500, 1000, 2000, 5000];
        
        for (const count of counts) {
            // 生成测试数据
            const rects = this.generateRectangles(count, 1920, 1080);
            
            // 标准版测试
            const standardTree = new Quadtree<Rectangle>({
                width: 1920,
                height: 1080
            });
            
            const standardStart = performance.now();
            for (const rect of rects) {
                standardTree.insert(rect);
            }
            const standardTime = performance.now() - standardStart;
            
            // 优化版测试（启用所有优化）
            const optimizedTree = new QuadtreeOptimized<Rectangle>({
                width: 1920,
                height: 1080,
                enableObjectPool: true,
                enableQueryCache: true,
                enableIncrementalUpdate: true
            });
            
            const optimizedStart = performance.now();
            for (const rect of rects) {
                optimizedTree.insert(rect);
            }
            const optimizedTime = performance.now() - optimizedStart;
            
            // 批量插入测试
            const batchTree = new QuadtreeOptimized<Rectangle>({
                width: 1920,
                height: 1080,
                enableObjectPool: true,
                enableQueryCache: true
            });
            
            const batchStart = performance.now();
            batchTree.insertBatch(rects);
            const batchTime = performance.now() - batchStart;
            
            const speedup1 = (standardTime / optimizedTime).toFixed(2);
            const speedup2 = (standardTime / batchTime).toFixed(2);
            
            Log.performance.info(`${count} 个对象`, {
                标准版: `${standardTime.toFixed(2)}ms`,
                优化版: `${optimizedTime.toFixed(2)}ms (${speedup1}x)`,
                批量插入: `${batchTime.toFixed(2)}ms (${speedup2}x)`
            });
        }
    }
    
    /**
     * 测试 2: 查询性能 + 缓存效果
     */
    static testQueryPerformance(): void {
        Log.styled('='.repeat(60), 'separator');
        Log.styled('测试 2: 查询性能 + 缓存效果', 'title');
        Log.styled('='.repeat(60), 'separator');
        
        const objectCount = 1000;
        const queryCount = 1000;
        
        const rects = this.generateRectangles(objectCount, 1920, 1080);
        const queryRects = this.generateRectangles(queryCount, 1920, 1080);
        
        // 标准版
        const standardTree = new Quadtree<Rectangle>({
            width: 1920,
            height: 1080
        });
        
        for (const rect of rects) {
            standardTree.insert(rect);
        }
        
        const standardStart = performance.now();
        let standardChecks = 0;
        for (const query of queryRects) {
            const results = standardTree.retrieve(query);
            standardChecks += results.length;
        }
        const standardTime = performance.now() - standardStart;
        
        // 优化版（无缓存）
        const optimizedNoCacheTree = new QuadtreeOptimized<Rectangle>({
            width: 1920,
            height: 1080,
            enableQueryCache: false
        });
        
        for (const rect of rects) {
            optimizedNoCacheTree.insert(rect);
        }
        
        const noCacheStart = performance.now();
        let noCacheChecks = 0;
        for (const query of queryRects) {
            const results = optimizedNoCacheTree.retrieve(query);
            noCacheChecks += results.length;
        }
        const noCacheTime = performance.now() - noCacheStart;
        
        // 优化版（有缓存）
        const optimizedCacheTree = new QuadtreeOptimized<Rectangle>({
            width: 1920,
            height: 1080,
            enableQueryCache: true
        });
        
        for (const rect of rects) {
            optimizedCacheTree.insert(rect);
        }
        
        // 首次查询（缓存未命中）
        const firstQueryStart = performance.now();
        for (const query of queryRects) {
            optimizedCacheTree.retrieve(query);
        }
        const firstQueryTime = performance.now() - firstQueryStart;
        
        // 第二次查询（缓存命中）
        const secondQueryStart = performance.now();
        for (const query of queryRects) {
            optimizedCacheTree.retrieve(query);
        }
        const secondQueryTime = performance.now() - secondQueryStart;
        
        const stats = optimizedCacheTree.getStats();
        
        Log.performance.info('查询性能对比', {
            标准版: `${standardTime.toFixed(2)}ms`,
            优化版无缓存: `${noCacheTime.toFixed(2)}ms`,
            优化版首次: `${firstQueryTime.toFixed(2)}ms`,
            优化版缓存: `${secondQueryTime.toFixed(2)}ms`,
            缓存加速: `${(firstQueryTime / secondQueryTime).toFixed(2)}x`,
            命中率: stats.cacheHitRate
        });
    }
    
    /**
     * 测试 3: 更新性能（增量更新 vs 常规更新）
     */
    static testUpdatePerformance(): void {
        Log.styled('='.repeat(60), 'separator');
        Log.styled('测试 3: 更新性能（增量更新）', 'title');
        Log.styled('='.repeat(60), 'separator');
        
        const objectCount = 1000;
        const updateCount = 100; // 更新 10% 的对象
        
        const rects = this.generateRectangles(objectCount, 1920, 1080);
        const toUpdate = rects.slice(0, updateCount);
        
        // 标准版（remove + insert）
        const standardTree = new Quadtree<Rectangle>({
            width: 1920,
            height: 1080
        });
        
        for (const rect of rects) {
            standardTree.insert(rect);
        }
        
        const standardStart = performance.now();
        for (const rect of toUpdate) {
            rect.x += 10;
            rect.y += 10;
            standardTree.update(rect, true);
        }
        const standardTime = performance.now() - standardStart;
        
        // 优化版（无增量更新）
        const optimizedNoIncrTree = new QuadtreeOptimized<Rectangle>({
            width: 1920,
            height: 1080,
            enableIncrementalUpdate: false
        });
        
        const rects2 = this.generateRectangles(objectCount, 1920, 1080);
        const toUpdate2 = rects2.slice(0, updateCount);
        
        for (const rect of rects2) {
            optimizedNoIncrTree.insert(rect);
        }
        
        const noIncrStart = performance.now();
        for (const rect of toUpdate2) {
            rect.x += 10;
            rect.y += 10;
            optimizedNoIncrTree.update(rect, true);
        }
        const noIncrTime = performance.now() - noIncrStart;
        
        // 优化版（有增量更新）
        const optimizedIncrTree = new QuadtreeOptimized<Rectangle>({
            width: 1920,
            height: 1080,
            enableIncrementalUpdate: true
        });
        
        const rects3 = this.generateRectangles(objectCount, 1920, 1080);
        const toUpdate3 = rects3.slice(0, updateCount);
        
        for (const rect of rects3) {
            optimizedIncrTree.insert(rect);
        }
        
        const incrStart = performance.now();
        for (const rect of toUpdate3) {
            rect.x += 10;
            rect.y += 10;
            optimizedIncrTree.update(rect, true);
        }
        const incrTime = performance.now() - incrStart;
        
        const stats = optimizedIncrTree.getStats();
        
        Log.performance.info('更新性能对比', {
            对象总数: objectCount,
            更新数量: updateCount,
            标准版: `${standardTime.toFixed(2)}ms`,
            优化版无增量: `${noIncrTime.toFixed(2)}ms`,
            优化版增量: `${incrTime.toFixed(2)}ms`,
            增量加速: `${(standardTime / incrTime).toFixed(2)}x`,
            增量更新数: stats.incrementalUpdates
        });
    }
    
    /**
     * 测试 4: 批量更新性能
     */
    static testBatchUpdate(): void {
        Log.styled('='.repeat(60), 'separator');
        Log.styled('测试 4: 批量更新性能', 'title');
        Log.styled('='.repeat(60), 'separator');
        
        const objectCount = 2000;
        const updateRatio = [0.1, 0.3, 0.5, 0.8]; // 更新比例
        
        for (const ratio of updateRatio) {
            const updateCount = Math.floor(objectCount * ratio);
            
            // 单个更新
            const tree1 = new QuadtreeOptimized<Rectangle>({
                width: 1920,
                height: 1080
            });
            
            const rects1 = this.generateRectangles(objectCount, 1920, 1080);
            for (const rect of rects1) {
                tree1.insert(rect);
            }
            
            const toUpdate1 = rects1.slice(0, updateCount);
            const singleStart = performance.now();
            for (const rect of toUpdate1) {
                rect.x += 10;
                tree1.update(rect, true);
            }
            const singleTime = performance.now() - singleStart;
            
            // 批量更新
            const tree2 = new QuadtreeOptimized<Rectangle>({
                width: 1920,
                height: 1080
            });
            
            const rects2 = this.generateRectangles(objectCount, 1920, 1080);
            for (const rect of rects2) {
                tree2.insert(rect);
            }
            
            const toUpdate2 = rects2.slice(0, updateCount);
            const batchStart = performance.now();
            for (const rect of toUpdate2) {
                rect.x += 10;
            }
            tree2.updateBatch(toUpdate2);
            const batchTime = performance.now() - batchStart;
            
            Log.performance.info(`更新 ${(ratio * 100).toFixed(0)}% 对象`, {
                对象数: updateCount,
                单个更新: `${singleTime.toFixed(2)}ms`,
                批量更新: `${batchTime.toFixed(2)}ms`,
                提升: `${(singleTime / batchTime).toFixed(2)}x`
            });
        }
    }
    
    /**
     * 测试 5: 对象池效果（GC 压力测试）
     */
    static testObjectPool(): void {
        Log.styled('='.repeat(60), 'separator');
        Log.styled('测试 5: 对象池效果（GC 压力）', 'title');
        Log.styled('='.repeat(60), 'separator');
        
        const iterations = 100;
        const objectsPerIteration = 1000;
        
        // 无对象池
        const noPoolTree = new QuadtreeOptimized<Rectangle>({
            width: 1920,
            height: 1080,
            enableObjectPool: false
        });
        
        const noPoolStart = performance.now();
        for (let i = 0; i < iterations; i++) {
            const rects = this.generateRectangles(objectsPerIteration, 1920, 1080);
            for (const rect of rects) {
                noPoolTree.insert(rect);
            }
            noPoolTree.clear();
        }
        const noPoolTime = performance.now() - noPoolStart;
        
        // 有对象池
        const poolTree = new QuadtreeOptimized<Rectangle>({
            width: 1920,
            height: 1080,
            enableObjectPool: true
        });
        
        const poolStart = performance.now();
        for (let i = 0; i < iterations; i++) {
            const rects = this.generateRectangles(objectsPerIteration, 1920, 1080);
            for (const rect of rects) {
                poolTree.insert(rect);
            }
            poolTree.clear();
        }
        const poolTime = performance.now() - poolStart;
        
        Log.performance.info('对象池效果', {
            迭代次数: iterations,
            每次对象数: objectsPerIteration,
            总操作数: iterations * objectsPerIteration,
            无池耗时: `${noPoolTime.toFixed(2)}ms`,
            有池耗时: `${poolTime.toFixed(2)}ms`,
            性能提升: `${(noPoolTime / poolTime).toFixed(2)}x`,
            GC压力降低: `${((1 - poolTime / noPoolTime) * 100).toFixed(1)}%`
        });
    }
    
    /**
     * 测试 6: 高级查询性能
     */
    static testAdvancedQueries(): void {
        Log.styled('='.repeat(60), 'separator');
        Log.styled('测试 6: 高级查询性能', 'title');
        Log.styled('='.repeat(60), 'separator');
        
        const objectCount = 1000;
        
        const tree = new QuadtreeOptimized<Rectangle>({
            width: 1920,
            height: 1080
        });
        
        const rects = this.generateRectangles(objectCount, 1920, 1080);
        for (const rect of rects) {
            tree.insert(rect);
        }
        
        // 矩形范围查询
        const rectStart = performance.now();
        for (let i = 0; i < 100; i++) {
            tree.queryRect(
                Math.random() * 1920,
                Math.random() * 1080,
                200,
                200
            );
        }
        const rectTime = performance.now() - rectStart;
        
        // 圆形范围查询
        const circleStart = performance.now();
        for (let i = 0; i < 100; i++) {
            tree.queryCircle(
                Math.random() * 1920,
                Math.random() * 1080,
                100
            );
        }
        const circleTime = performance.now() - circleStart;
        
        // K 近邻查询
        const knnStart = performance.now();
        for (let i = 0; i < 100; i++) {
            tree.queryKNearest(
                Math.random() * 1920,
                Math.random() * 1080,
                10
            );
        }
        const knnTime = performance.now() - knnStart;
        
        Log.performance.info('高级查询性能', {
            对象数: objectCount,
            查询次数: 100,
            矩形查询: `${rectTime.toFixed(2)}ms (${(rectTime / 100).toFixed(3)}ms/次)`,
            圆形查询: `${circleTime.toFixed(2)}ms (${(circleTime / 100).toFixed(3)}ms/次)`,
            KNN查询: `${knnTime.toFixed(2)}ms (${(knnTime / 100).toFixed(3)}ms/次)`
        });
    }
    
    /**
     * 测试 7: 内存使用对比
     */
    static testMemoryUsage(): void {
        Log.styled('='.repeat(60), 'separator');
        Log.styled('测试 7: 内存使用对比', 'title');
        Log.styled('='.repeat(60), 'separator');
        
        const objectCounts = [100, 500, 1000, 2000, 5000];
        
        if (typeof (performance as any).memory !== 'undefined') {
            for (const count of objectCounts) {
                // 强制 GC（如果可用）
                if (typeof (globalThis as any).gc === 'function') {
                    (globalThis as any).gc();
                }
                
                const beforeMem = (performance as any).memory.usedJSHeapSize;
                
                // 创建标准树
                const standardTree = new Quadtree<Rectangle>({
                    width: 1920,
                    height: 1080
                });
                
                const rects = this.generateRectangles(count, 1920, 1080);
                for (const rect of rects) {
                    standardTree.insert(rect);
                }
                
                const standardMem = (performance as any).memory.usedJSHeapSize - beforeMem;
                
                // 清理
                standardTree.clear();
                
                if (typeof (globalThis as any).gc === 'function') {
                    (globalThis as any).gc();
                }
                
                const beforeMem2 = (performance as any).memory.usedJSHeapSize;
                
                // 创建优化树
                const optimizedTree = new QuadtreeOptimized<Rectangle>({
                    width: 1920,
                    height: 1080,
                    enableObjectPool: true
                });
                
                const rects2 = this.generateRectangles(count, 1920, 1080);
                for (const rect of rects2) {
                    optimizedTree.insert(rect);
                }
                
                const optimizedMem = (performance as any).memory.usedJSHeapSize - beforeMem2;
                
                Log.performance.info(`${count} 个对象`, {
                    标准版: `${(standardMem / 1024).toFixed(2)} KB`,
                    优化版: `${(optimizedMem / 1024).toFixed(2)} KB`,
                    节省: `${((1 - optimizedMem / standardMem) * 100).toFixed(1)}%`
                });
                
                optimizedTree.destroy();
            }
        } else {
            Log.performance.warn('performance.memory 不可用，跳过内存测试');
        }
    }
    
    /**
     * 运行所有测试
     */
    static runAllTests(): void {
        Log.styled('🧪 优化版 vs 标准版 Quadtree 性能对比开始', 'large');
        Log.styled('━'.repeat(60), 'separator');
        
        this.testMassiveInsert();
        this.testQueryPerformance();
        this.testUpdatePerformance();
        this.testBatchUpdate();
        this.testObjectPool();
        this.testAdvancedQueries();
        this.testMemoryUsage();
        
        Log.styled('━'.repeat(60), 'separator');
        Log.styled('✅ 所有测试完成！', 'success');
    }
    
    /**
     * 生成随机矩形
     */
    private static generateRectangles(count: number, width: number, height: number): Rectangle[] {
        const rects: Rectangle[] = [];
        
        for (let i = 0; i < count; i++) {
            rects.push(new Rectangle({
                x: Math.random() * (width - 50),
                y: Math.random() * (height - 50),
                width: 20 + Math.random() * 30,
                height: 20 + Math.random() * 30,
                data: { id: i }
            }));
        }
        
        return rects;
    }
}

